package com.tea.modules.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.parser.*;
import com.alibaba.fastjson.serializer.*;
import com.alibaba.fastjson.support.config.FastJsonConfig;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageNotReadableException;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 *  Fastjson工具类
 * @author admin
 *
 */
public class JsonUtils {

    protected static Logger logger = LoggerFactory.getLogger(JsonUtils.class);

    private static final SerializeConfig FASTJSON_SERIALIZE_CONFIG;

    static {
        FASTJSON_SERIALIZE_CONFIG = new SerializeConfig();

    }

    private static final SerializerFeature[] SERIALIZER_FEATURES = {
    		// 输出空置字段
            SerializerFeature.WriteMapNullValue,
            // list字段如果为null，输出为[]，而不是null
            SerializerFeature.WriteNullListAsEmpty,
            // 数值字段如果为null，输出为0，而不是null
            SerializerFeature.WriteNullNumberAsZero,
            // Boolean字段如果为null，输出为false，而不是null
            SerializerFeature.WriteNullBooleanAsFalse,
            // 字符类型字段如果为null，输出为""，而不是null
            SerializerFeature.WriteNullStringAsEmpty,
            //禁止循环引用$ref
            SerializerFeature.DisableCircularReferenceDetect,
            //枚举转字符串
            SerializerFeature.WriteEnumUsingToString
    };

    private static final SerializerFeature[] SERIALIZER_PRETTY_FEATURES = {
    		// 输出空置字段
    		SerializerFeature.WriteMapNullValue,
    		// list字段如果为null，输出为[]，而不是null
            SerializerFeature.WriteNullListAsEmpty,
            // 数值字段如果为null，输出为0，而不是null
            SerializerFeature.WriteNullNumberAsZero,
            // Boolean字段如果为null，输出为false，而不是null
            SerializerFeature.WriteNullBooleanAsFalse,
            // 字符类型字段如果为null，输出为""，而不是null
            SerializerFeature.WriteNullStringAsEmpty,
            //禁止循环引用$ref
            SerializerFeature.DisableCircularReferenceDetect,
            //枚举转字符串
            SerializerFeature.WriteEnumUsingToString,
            //美化输出
            SerializerFeature.PrettyFormat
    };

    private static final SerializeFilter[] SERIALIZER_FILTERS = {
//        new NullObjectFilter()
    };

    private static final Feature[] FEATURE = {
        Feature.IgnoreNotMatch
    };

    public static String toString(Object object) {
        return JSON.toJSONString(object, FASTJSON_SERIALIZE_CONFIG, SERIALIZER_FILTERS, SERIALIZER_FEATURES);
    }

    public static String toPrettyString(Object object) {
        String json = JSON.toJSONString(object, FASTJSON_SERIALIZE_CONFIG, SERIALIZER_FILTERS, SERIALIZER_PRETTY_FEATURES);
        return StringUtils.replace(json, "\t", "  ");
    }

    public static Object toBean(String text) {
        return JSON.parse(text, FEATURE);
    }

    public static <T> T toBean(String text, Class<T> clazz) {
        return JSON.parseObject(text, clazz, FEATURE);
    }

    public static <T> T toBean(InputStream content, Class<T> clazz) {
        try {
            return JSON.parseObject(content, clazz, FEATURE);
        } catch (IOException e) {
            logger.error("InputStream toBean error ", e);
        }
        return null;
    }

    /**
     * 转换为数组
     */
    public static <T> Object[] toArray(String text) {
        return toArray(text, null);
    }

    /**
     * 转换为数组
     */
    public static <T> Object[] toArray(String text, Class<T> clazz) {
        return JSON.parseArray(text, clazz).toArray();
    }

    /**
     * 转换为List
     */
    public static <T> List<T> toList(String text, Class<T> clazz) {
        return JSON.parseArray(text, clazz);
    }

    /**
     * 转换为字节
     */
    public static byte[] toBytes(Object object){
        return toString(object).getBytes();
    }

    /**
     * 转换对象
     */
    public static <T> T toBean(byte[] bytes, Class<T> clazz){
        return toBean(new String(bytes), clazz);
    }

    /**
     * 将对象转化为map
     * @param object
     * @return
     */
    public static Map toMap(Object object) {
        Map m = toMap(toString(object));
        return m;
    }

    /**
     * json字符串转化为map
     * @param s
     * @return
     */
    public static Map toMap(String s) {
        Map m = JSONObject.parseObject(s);
        return m;
    }

    /**
     * 获取转换器
     * @return
     */
    public static FastJsonHttpMessageConverter getConverter(){
        FastJsonHttpMessageConverter fastConverter = new MvcHttpConverter();
        FastJsonConfig fastJsonConfig = new FastJsonConfig();
        fastJsonConfig.setSerializeConfig(FASTJSON_SERIALIZE_CONFIG);
        fastJsonConfig.setSerializerFeatures(SERIALIZER_FEATURES);
        fastJsonConfig.setSerializeFilters(SERIALIZER_FILTERS);
        fastJsonConfig.setFeatures(FEATURE);
        List<MediaType> fastMediaTypes = new ArrayList<>();
        fastMediaTypes.add(MediaType.APPLICATION_JSON_UTF8);
        fastMediaTypes.add(MediaType.APPLICATION_JSON);
        fastConverter.setSupportedMediaTypes(fastMediaTypes);
        fastConverter.setFastJsonConfig(fastJsonConfig);

        return fastConverter;
    }

}

class MvcHttpConverter extends FastJsonHttpMessageConverter{

    @Override
    public Object read(Type type, Class<?> contextClass, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {
        return readWithParserConfig(getType(type, contextClass), inputMessage);
    }

    @Override
    protected Object readInternal(Class<? extends Object> clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {
        return readWithParserConfig(getType(clazz, null), inputMessage);
    }

    private Object readWithParserConfig(Type type, HttpInputMessage inputMessage) throws IOException {
        try {
            FastJsonConfig config = getFastJsonConfig();
            InputStream in = inputMessage.getBody();
            String json = IOUtils.toString(in, config.getCharset());
            return JSON.parseObject(json, type, config.getParserConfig(), config.getFeatures());
        } catch (JSONException ex) {
            throw new HttpMessageNotReadableException("JSON parse error: " + ex.getMessage(), ex);
        } catch (IOException ex) {
            throw new HttpMessageNotReadableException("I/O error while reading input message", ex);
        }
    }
}

/**
 * 日期格式
 */
class DataFormatSerializer extends SimpleDateFormatSerializer {
    public DataFormatSerializer(String pattern) {
        super(pattern);
    }
    @Override
    public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features) throws IOException {
        if(object == null) {
            serializer.out.writeString("");
        } else {
            super.write(serializer, object, fieldName, fieldType, features);
        }
    }
}

